
/*************
author:: libo
license:: MIT
*****************/
#ifndef LIB_CELL_MESH_FRAME_H_
#define LIB_CELL_MESH_FRAME_H_
#include "Cell_Traits.h"

/***********give some points p0 p1 ..pn then the
Antisymmetric tensor is

 (p1-p0)/\(p2-p0)/\...(pn-p0)*****

***/
//#define mesh_frame_dim_sizet char

//unsigned char

#ifndef SAFE_FREE
#define SAFE_FREE(x) if(x!=NULL){free(x);x=NULL;}
#endif
#ifdef __cplusplus
extern "C"{
#endif


typedef struct Vertex {
    LB_Vector1_voidptr cellsn;
    LB_Vector1_voidptr facesn;
    double *point;
    void *prop;
    int id;                     // 4 bytes
    unsigned int point_size;    // 4 bytes

#ifdef LIBCELL_USING_TRAITS
    VertexT traits;             // Size depends on the actual type of VertexT
#endif
} Vertex;

// typedef struct Vertex{
//     int id;
//     double *point;
//     unsigned int point_size;

//     // Node *cells;
//     // Node *faces;
//     LB_Vector1_voidptr cellsn,facesn;


//     void *prop;
//     //*user_prop;
// #ifdef LIBCELL_USING_TRAITS
// 	VertexT traits;
// #endif
// }Vertex;
typedef struct HalfFace {
    struct Vertex** vertices;  // 8 bytes
    struct Cell* cell;         // 8 bytes
    struct Face* face;         // 8 bytes
    void *prop;                // 8 bytes
    unsigned int vertices_size;// 4 bytes
    int id;                    // 4 bytes

#ifdef LIBCELL_USING_TRAITS
    HalfT traits;              // Size depends on the actual type of HalfT
#endif
} HalfFace;

// typedef struct HalfFace{
//     int id;
//     struct Vertex** vertices;
//     unsigned int vertices_size;

//     struct Cell* cell;
//     struct Face* face;
//     void *prop;
//     //*user_prop;
// #ifdef LIBCELL_USING_TRAITS
//     HalfT traits;
// #endif
// }HalfFace;
typedef struct Face {
    struct Vertex** vertices;
    struct HalfFace* halffaces[2];
    void *prop;

    unsigned int vertices_size;
    int id;

#ifdef LIBCELL_USING_TRAITS
    FaceT traits;
#endif
} Face;
// typedef struct Face{
//     int id;
//     struct Vertex**vertices;
//     unsigned int vertices_size;
//     struct HalfFace* halffaces[2];
// //int halffaces_size;

//     void *prop;
//     //*user_prop;
// #ifdef LIBCELL_USING_TRAITS
//     FaceT traits;
// #endif
// }Face;
typedef struct Cell {
    struct Vertex** vertices;
    struct HalfFace** halffaces;
    void *prop;

    unsigned int vertices_size;
    unsigned int halffaces_size;
    int id;

#ifdef LIBCELL_USING_TRAITS
    CellT traits;
#endif
} Cell;
// typedef struct Cell{
//     int id;
//     struct Vertex**vertices;
//     unsigned int vertices_size;
//     struct HalfFace** halffaces;
//     unsigned int halffaces_size;
//     //Node* halffaces;
//     void *prop;
//     //*user_prop;
// #ifdef LIBCELL_USING_TRAITS
//     CellT traits;
// #endif
// }Cell;
//void Vertex_init_(Vertex*);
static inline void Vertex_init_(Vertex* pv)
{

    // pv->cells=NULL;
    // pv->faces=NULL;
    lb_vector1_init_voidptr(&(pv->cellsn) );
    lb_vector1_init_voidptr(&(pv->facesn) );

    pv->id=-1;
    pv->point=NULL;
    pv->point_size=0;
    pv->prop=NULL;
   // pv->user_prop=NULL;
#ifdef LIBCELL_USING_TRAITS
    vertexT_init(&(pv->traits));
#endif
}

static inline void HalfFace_init_(HalfFace *hf)
{
    hf->vertices=NULL;
    hf->vertices_size=0;

    hf->cell=NULL;
    hf->face=NULL;
    hf->prop=NULL;
    //hf->user_prop=NULL;
    hf->id=-1;
#ifdef LIBCELL_USING_TRAITS
    halfT_init(&(hf->traits));
#endif
}


static inline void Face_init_(Face *f)
{
    f->prop=NULL;
    //f->user_prop=NULL;
    f->vertices=NULL;
    f->id=-1;
    f->halffaces[0]=(template_hf*)malloc(sizeof(template_hf));
    f->halffaces[1]=(template_hf*)malloc(sizeof(template_hf));
    HalfFace_init_(f->halffaces[0]);
    HalfFace_init_(f->halffaces[1]);
    f->halffaces[0]->face=f;
    f->halffaces[1]->face=f;
     f->vertices_size=0;
#ifdef LIBCELL_USING_TRAITS
    faceT_init(&(f->traits));
#endif
}
static inline void Cell_init_(Cell *c)
{
    c->vertices=NULL;
    c->halffaces=NULL;
    c->id=-1;
    c->vertices_size=0;
    c->halffaces_size=0;
    c->prop=NULL;
    //pv->user_prop=NULL;
#ifdef LIBCELL_USING_TRAITS
    cellT_init(&(pv->traits));
#endif
}


static inline void free_Vertex(Vertex*v)
{
    if(v->point!=NULL)
    {
        free(v->point);
        v->point=NULL;
    }
    lb_vector1_clear_voidptr(&(v->facesn));
    lb_vector1_clear_voidptr(&(v->cellsn));

//     if(v->faces!=NULL)
//     {
//         free_node(v->faces);
//         v->faces=NULL;
//     }
// //free_node(v->faces);
//     if(v->cells!=NULL)
//     {
//         free_node(v->cells);
//         v->cells=NULL;
//     }
    free(v);
}

static inline void free_HalfFace(HalfFace *hf)
{
    if(hf->vertices!=NULL)
    {
        free(hf->vertices);
        hf->vertices=NULL;
    }
    free(hf);

}

static inline void free_Face(Face*f)
{
    //printf("here1\n");
    if(f==NULL)
    {
        printf("cuowu\n");
        return;
    }
    if(f->vertices!=NULL)
    {
        free(f->vertices);
        f->vertices=NULL;
    }
    free_HalfFace(f->halffaces[0]);
    free_HalfFace(f->halffaces[1]);
    free(f);
}
static inline void free_Cell(Cell*c)
{
    if(c->vertices!=NULL)
    {
        free(c->vertices);
        c->vertices=NULL;c->vertices_size=0;
    }
    if(c->halffaces!=NULL)
    {
        free(c->halffaces);
        //free_node(c->halffaces);
        c->halffaces=NULL;c->halffaces_size=0;
    }
    free(c);
}
static inline void Halfface_remove_c(HalfFace*hf,Cell*c)
{
    if(hf==NULL||c==NULL)
    {return;}
    if(hf->cell==c)
    {
        hf->cell=NULL;
    }
}



static inline void Face_remove_c(Face*f ,Cell*c)
{
    if(c==NULL)
    {
        return ;
    }
    if((f->halffaces[0])->cell==c)
    {
        ((template_hf*)f->halffaces[0])->cell=NULL;
    }
    else if(((template_hf*)f->halffaces[1])->cell==c)
    {
        ((template_hf*)f->halffaces[1])->cell=NULL;
    }

}
static inline void Vertex_remove_f(Vertex*v,Face*f)
{
    lb_vector1_remove_voidptr(&(v->facesn),f);

    // Node* node=node_find(v->faces,(void*)f);
    // if(node==NULL)
    // {
    //     return;
    // }
    // Node* node1=(Node*)(node->Prev),*node2=(Node*)(node->Next);
    // node1!=NULL?(node1->Next=node2):(v->faces=node2);

    // if(node2!=NULL)
    // {
    //     node2->Prev=(void*)node1;
    // }
    // free(node);
}
static inline void Vertex_remove_c(Vertex*v,Cell*c)
{
    lb_vector1_remove_voidptr(&(v->cellsn),c);

    // Node* node=node_find(v->cells,(void*)c);
    // if(node==NULL)
    // {
    //     return;
    // }
    // Node* node1=(Node*)(node->Prev),*node2=(Node*)(node->Next);
    // node1!=NULL?(node1->Next=node->Next):(v->cells=node2);
    // if(node2!=NULL)
    // {
    //     node2->Prev=(void*)node1;
    // }
    // free(node);
}


// static inline void Cell_remove_hf(Cell*c,HalfFace*f)
// {
//     Node*node=node_find(c->halffaces,(void*)f);
//     if(node==NULL)
//     {
//         return;
//     }
//     Node* node1=(Node*)(node->Prev),*node2=(Node*)(node->Next);
//     node1!=NULL?(node1->Next=node2):(c->halffaces=node2);

//     if(node2!=NULL)
//     {
//         node2->Prev=(void*)node1;
//     }
//     free(node);
// }

//#undef mesh_frame_dim_sizet
#ifdef __cplusplus
}
#endif
#endif
